home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / _archvrs / unix / zoo-2_1.lha / zoo-2.1 / misc.c < prev    next >
C/C++ Source or Header  |  1991-10-01  |  10KB  |  375 lines

  1. #ifndef LINT
  2. /* derived from: misc.c 2.6 88/08/15 16:17:23 */
  3. static char sccsid[]="$Source: /usr/home/dhesi/zoo/RCS/misc.c,v $\n\
  4. $Id: misc.c,v 1.8 91/07/09 01:54:08 dhesi Exp $";
  5. #endif /* LINT */
  6.  
  7. /*
  8. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  9. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  10. */
  11. #include "options.h"
  12. /* Miscellaneous functions needed by Zoo but not by Ooz */
  13.  
  14. #include "zoo.h"
  15. #include "zooio.h"
  16. #include "various.h"
  17.  
  18. #include "errors.i"
  19. #include "zoofns.h"
  20. #ifndef NOSIGNAL
  21. #include <signal.h>
  22. #endif
  23.  
  24. #ifdef NEEDCTYP
  25. #include <ctype.h>
  26. #else
  27. #include "portable.h"
  28. #endif
  29.  
  30. int ver_too_high PARMS((struct zoo_header *));
  31.  
  32. /*
  33. calc_ofs() is given a string that (supposedly) begins with a string
  34. of digits.  It returns a corresponding numeric value.  If no such
  35. string, it aborts the program with a fatal error message.
  36. */
  37. long calc_ofs(str)
  38. char *str;
  39. {
  40.    long retval;
  41.    char *p;
  42.    retval = 0L;
  43.    p = str; /* save for error message */
  44.    while (isdigit(*str)) {
  45.       retval = retval * 10L + (*str-'0');
  46.       str++;
  47.    }
  48.    if (*str != '\0')
  49.       prterror ('f', "Invalid number %s\n", p);
  50.    return (retval);
  51. }
  52.  
  53. /*
  54. choosefname() decides which filename to use.  If a long filename is present,
  55. and if the syntax is that of UNIX, MS-DOS or the portable form, we use it;
  56. else we use the short filename. 
  57. */
  58.  
  59. char *choosefname(direntry)
  60. struct direntry *direntry;
  61. {
  62.    char *retptr;                 /* pointer to name that we will return */
  63.    switch (direntry->system_id) {
  64.       case SYSID_NIX:
  65.       case SYSID_PORTABLE:
  66.       case SYSID_MS:
  67.          retptr = (direntry->namlen != 0) ? direntry->lfname : direntry->fname;
  68.          break;
  69.       default:
  70.          retptr = direntry->fname;
  71.          break;
  72.    }
  73.    return (retptr);
  74. } /* choosefname() */
  75.  
  76. /* 
  77. combine() combines a directory name and a filename, making sure the
  78. two are separated by a path separator 
  79. */
  80. char *combine(result, dirname, fname)
  81. char result[], *dirname, *fname;
  82. {
  83.    *result = '\0';
  84.    if (*dirname != '\0') {
  85. #ifdef DIR_LBRACK /* hack for VMS */
  86.       strcat (result, DIR_LBRACK);
  87.  
  88.       /*  "/" => "[",  "./" => "[."  others => "[." */
  89.  
  90.       if (dirname[0] == '/') {        /* absolute path => "[" */
  91.          strcat (result, dirname + 1);
  92.       } else if (dirname[0] == '.' && dirname[1] == '/') {
  93.          strcat (result, CUR_DIR);
  94.          strcat (result, dirname + 2);
  95.       } else {
  96.          strcat (result, CUR_DIR);
  97.          strcat (result, dirname);
  98.       }
  99.  
  100. /* folowing #ifdef block ought to be outside #ifdef DIR_LBRACK, and
  101.    for loop should then start with p=result.  This is currently
  102.    just a hack for VMS.
  103. */
  104. #ifdef DIR_SEP
  105.    if (DIR_SEP != '/') {   /* if char separating dirs is not "/",  */
  106.       char *p;
  107.       for (p = result+2;  *p != '\0';  p++) /* change it to underscore */
  108.         if (*p == DIR_SEP)
  109.            *p = '_';
  110.    }
  111. #endif
  112.  
  113.       {
  114.          char *p;
  115.          for (p = result; *p != '\0';  p++)
  116.          if (*p == '/')
  117.             *p = '.';
  118.       }
  119. #else
  120.       strcat (result, dirname);
  121. #endif
  122.       if (*lastptr(result) != *PATH_CH)
  123.          strcat(result, PATH_CH);
  124.    }
  125.  
  126.    strcat(result, fname);
  127.    return (result);
  128. }
  129.  
  130. /*
  131. fullpath() accepts a pointer to a directory entry and returns the
  132. combined directory name + filename.  The long filename is used
  133. if available, else the short filename is used.
  134. */
  135. char *fullpath (direntry)
  136. struct direntry *direntry;
  137. {
  138.     static char result[PATHSIZE];
  139.     combine (result,
  140.                 direntry->dirlen != 0 ? direntry->dirname : "", 
  141.                 (direntry->namlen != 0) ? direntry->lfname : direntry->fname
  142.               );
  143.     return (result);
  144. }
  145.  
  146. /* 
  147. ver_too_high returns true if version of provided archive header is
  148. too high for us to manipulate archive
  149. */
  150.  
  151. int ver_too_high (header)
  152. struct zoo_header *header;
  153. {
  154.    return (header->major_ver > MAJOR_VER ||
  155.             (header->major_ver == MAJOR_VER &&
  156.              header->minor_ver > MINOR_VER));
  157. }
  158.  
  159. /* 
  160. rwheader() reads archive header, checks consistency, makes sure its
  161. version number is not too high, updates it if too low, and seeks to
  162. beginning of first directory entr.  If `preserve' is 1, it preserves
  163. the header type;  if `preserve' is 0, it gives a fatal error message
  164. if type is 0.
  165. */
  166.  
  167. void rwheader (header, zoo_file, preserve)
  168. register struct zoo_header *header;
  169. ZOOFILE zoo_file;
  170. int preserve;
  171. {
  172.  
  173.    frd_zooh (header, zoo_file);
  174.  
  175.    if ((header->zoo_start + header->zoo_minus) != 0L)
  176.       prterror ('f', failed_consistency);
  177.    if (ver_too_high (header))
  178.       prterror ('f', wrong_version, header->major_ver, header->minor_ver);
  179.  
  180.     if (preserve == 0 && header->type == 0)
  181.         prterror ('f', packfirst);
  182.  
  183.    /* We reach here if the archive version is not too high.  Now, if it
  184.    isn't the same as ours, we bring it up to ours so the modified archive
  185.    will be safe from previous versions of Zoo */
  186.  
  187.    if (header->major_ver != MAJOR_VER || header->minor_ver != MINOR_VER) {
  188.       header->major_ver = MAJOR_VER;
  189.       header->minor_ver = MINOR_VER;
  190.       zooseek (zoo_file, 0L, 0);            /* seek to beginning */
  191.       fwr_zooh (header, zoo_file);
  192.    }
  193.    zooseek (zoo_file, header->zoo_start, 0); /* seek to where data begins */
  194. } /* rwheader */
  195.  
  196. /*
  197. writedir() write a directory entry with keyboard interrupt disabled
  198. */
  199. void writedir (direntry, zoo_file)
  200. struct direntry *direntry;
  201. ZOOFILE zoo_file;
  202. {
  203. #ifndef NOSIGNAL  
  204.    T_SIGNAL (*oldsignal)();
  205.    oldsignal = signal (SIGINT, SIG_IGN);
  206. #endif
  207.    if (fwr_dir (direntry, zoo_file) == -1)
  208.       prterror ('f', disk_full);
  209. #ifndef NOSIGNAL
  210.    signal (SIGINT, oldsignal);
  211. #endif
  212. }
  213.  
  214. /* 
  215. readdir() reads a directory entry from an archive.  If the directory
  216. entry is invalid and if fail is 1, it causes a fatal error;
  217. else it returns.  Return value is 0 if no error else -1;
  218. */
  219.  
  220. int readdir (direntry, zoo_file, fail)    /* read directory entry */
  221. register struct direntry *direntry;
  222. ZOOFILE zoo_file;
  223. int fail;                              /* 0 -> return, 1 -> abort on error */
  224. {
  225.    if (frd_dir (direntry, zoo_file) < 0) {
  226.       if (fail) {
  227.          prterror ('f', bad_directory);
  228.       } else
  229.          return (-1);
  230.    }
  231.    if (direntry->zoo_tag != ZOO_TAG) {
  232.       if (fail)
  233.          prterror ('f', bad_directory);
  234.       else
  235.          return (-1);
  236.    }
  237.    return (0);
  238. }
  239.  
  240. /* use pointer version below */
  241. #ifdef COMMENT
  242. /* instr() searches a string for a substring */
  243. instr (s, t)      /* return index of string t in string s, -1 if none */
  244. char s[], t[];    /*  .. from K&R page 67 */
  245. {
  246.    int i;
  247.    register int j, k;
  248.    for (i = 0; s[i] != '\0'; i++) {
  249.       for (j = i, k = 0; t[k] != '\0' && s[j]==t[k]; j++, k++)
  250.          ;
  251.       if (t[k] == '\0')
  252.          return (i);
  253.    }
  254.    return (-1);
  255. }
  256. #endif /* COMMENT */
  257.  
  258. /* instr() searches a string for a substring */
  259. /* from J. Brian Waters */
  260. int instr (s, t)           /* return the position of t in s, -1 if none */
  261. char *s, *t;                /*  a pointer version of K&R index function p.67 */
  262. {               /* renamed to instr() to avoid conflicts with C RTL - JBW */
  263.  
  264.    register char *i, *j, *k;
  265.  
  266.    for (i = s; *i; i++) {
  267.       for (j = i, k = t; (*k) && (*j++ == *k); k++)
  268.          ;
  269.        if (!*k)
  270.          return ((int) (i - s));
  271.    }
  272.    return(-1);
  273. }
  274.  
  275. /* cfactor() calculates the compression factor given a directory entry */
  276. int cfactor (org_size, size_now)
  277. long org_size, size_now;
  278. {
  279.    register int size_factor;
  280.    while ((unsigned long) org_size > 32000) { /* avoid later overflow */
  281.       org_size = (unsigned long) org_size / 1024;
  282.       size_now = (unsigned long) size_now / 1024;
  283.    }
  284.    if (org_size == 0)         /* avoid division by zero */
  285.       size_factor = 0;
  286.    else {
  287.       size_factor = (int)
  288.          (
  289.             (1000 * 
  290.                ((unsigned long) org_size - (unsigned long) size_now)
  291.             ) / org_size + 5
  292.          ) / 10;
  293.    }
  294.    return (size_factor);
  295. }
  296.  
  297. /***********
  298. str_dup() duplicates a string using dynamic memory.
  299. */
  300.  
  301. char *str_dup (str)
  302. register char *str;
  303. {
  304.    return (strcpy (emalloc (strlen(str)+1), str));
  305. }
  306.  
  307. /**************
  308. cmpnum() compares two pairs of unsigned integers and returns a negative,
  309. zero, or positive value as the comparison yields less than, equal, or
  310. greater than result.  Each pair of unsigned integers is considered to be the
  311. more significant and the less significant half of a longer unsigned number.
  312.  
  313. Note:  cmpnum is used to compare dates and times.
  314. */
  315.  
  316. int cmpnum (hi1, lo1, hi2, lo2)
  317. register unsigned int hi1, hi2;
  318. unsigned int lo1, lo2;
  319. {
  320.    if (hi1 != hi2)
  321.       return (hi1 > hi2 ? 1 : -1);
  322.    else {
  323.         if (lo1 == lo2)
  324.             return (0);
  325.         else
  326.             return (lo1 > lo2 ? 1 : -1);
  327.     }
  328. }
  329.  
  330. /*******************/
  331. /* writenull() */
  332. /* writes a null directory entry to an open archive */
  333. void writenull (file, length)
  334. ZOOFILE file;
  335. int length;
  336. {
  337. #ifndef NOSIGNAL
  338.    T_SIGNAL (*oldsignal)();
  339. #endif
  340.    struct direntry newentry;
  341.    memset ((char *) &newentry, 0, sizeof (newentry));
  342.    newentry.zoo_tag = ZOO_TAG;
  343.    newentry.type = 2;
  344.    /* Force entry to be the required length plus possibly 2 stray bytes
  345.    by dividing up the needed padding into dirlen and namlen. */
  346.    if (length > SIZ_DIRL)
  347.       newentry.dirlen = newentry.namlen = (length-SIZ_DIRL)/2 + 2;
  348.    else
  349.       newentry.dirlen = newentry.namlen = 0;
  350. #ifndef NOSIGNAL
  351.    oldsignal = signal (SIGINT, SIG_IGN);
  352. #endif
  353.    if (fwr_dir (&newentry, file) == -1)
  354.       prterror ('f', disk_full);
  355. #ifndef NOSIGNAL
  356.    signal (SIGINT, oldsignal);
  357. #endif
  358. }
  359.  
  360. #ifdef FORCESLASH
  361. /*******************/
  362. /*
  363. fixslash() changes all "\" characters in the supplied string to "/".
  364. */
  365.  
  366. void fixslash (str)
  367. char *str;
  368. {
  369.    register char *p;
  370.    for (p = str; *p != '\0'; p++)
  371.       if (*p == '\\')
  372.          *p = '/';
  373. }
  374. #endif /* FORCESLASH */
  375.